from sanic import Sanic
from sanic.response import text
from sanic.response import json
import requests
import cv2
import base64
import time
import json as Json
import re
import difflib
import numpy as np
import os
from datetime import datetime
from sfz_ocr import sfz_ocr_predict
from sanic.log import logger
from paddleocr import PaddleOCR


app = Sanic("table-server")
ocr = PaddleOCR(use_pdserving=False, use_angle_cls=True, det=True, cls=True, lang='ch', show_log=False,
                cls_thresh=0.9, use_gpu=True, det_db_box_thresh=0.4, det_db_score_mode='slow',
                det_model_dir='./inference/sfz_det_infer', 
                rec_model_dir='./inference/ch_ppocr_server_v2.0_rec_infer', 
                cls_model_dir='./inference/ch_ppocr_mobile_v2.0_cls_infer')
app.config.setdefault('ocr', ocr)
back_ocr = PaddleOCR(use_pdserving=False, use_angle_cls=True, det=True, cls=True, lang='ch', show_log=False,
                cls_thresh=0.9, use_gpu=True, det_db_box_thresh=0.4, det_db_score_mode='slow',
                det_model_dir='./inference/ch_PP-OCRv2_det_infer', 
                rec_model_dir='./inference/ch_ppocr_server_v2.0_rec_infer', 
                cls_model_dir='./inference/ch_ppocr_mobile_v2.0_cls_infer')
app.config.setdefault('back_ocr', back_ocr)


@app.post("/idfront/predict")
async def hello_world(request):
    res = {
        'msg': 'ok',
        'code': 0,
        'data': {
            "name": "",
            "idNo": "",
            "gender": "",
            "nation": "", 
            "birthday": "", 
            "address": "",
            "source_str_arr": []
        }
    }
    if len(request.files.keys()) != 1:
        res['msg'] = '必须传入一个图片'
        res['code'] = 1
        return json(res)
    f = request.files.get(list(request.files.keys())[0])
    input_img = cv2.imdecode(np.frombuffer(f.body, np.uint8), cv2.IMREAD_COLOR)
    return_dict = res['data']
    res_ls = []
    try:
        result = app.config['ocr'].ocr(input_img)
        for line in result:
            res_ls.append(line[1][0])
    except Exception as e:
        logger.exception(e)
    source_str_arr = []
    for item in res_ls:
        try:
            if '姓名' in item:
                return_dict['name'] = item.split('姓名')[1].replace(' ', '')
            elif len(item) == 18 and (item.isnumeric() or item[:-1].isnumeric()) and len(return_dict['idNo']) < 18:
                return_dict['idNo'] = item
            elif '公民身份号码' in item and item != '公民身份号码' and len(return_dict['idNo']) < 18:
                return_dict['idNo'] = item.replace('公民身份号码', '').replace(' ', '')
            elif '性别' in item:
                return_dict['gender'] = item.split('性别')[1].replace(' ', '')
            elif '女' == item:
                return_dict['gender'] = '女'
            elif '男' == item:
                return_dict['gender'] = '男'
            elif '民族' in item:
                return_dict['nation'] = item.split('民族')[1].replace(' ', '')
            elif '出生' in item:
                return_dict['birthday'] = '-'.join(re.findall( r'\d+', item, re.M|re.I))
                try:
                    return_dict['birthday'] = time.strftime('%Y-%m-%d', time.strptime(return_dict['birthday'], "%Y-%m-%d"))
                except Exception as e:
                    return_dict['birthday'] = ''
            elif '住址' in item:
                return_dict['address'] = item.replace('住址', '').replace(' ', '')
            elif item == '公民身份号码':
                continue
            elif item.replace(' ', '') in ['中华人民共和国', '居民身份证', '签发机关', '有效期限']:
                continue
            else:
                address = return_dict.get('address', '')
                address += item
                return_dict['address'] = address
        except Exception as e:
            logger.error(f'error {e}')
        finally:
            source_str_arr.append(item)
    if return_dict.get('idNo') and len(return_dict['idNo']) == 18 and len(return_dict.get('birthday', '')) != 10:
        return_dict['birthday'] = '%s-%s-%s' % (return_dict['idNo'][6:10], return_dict['idNo'][10:12], return_dict['idNo'][12:14])
    if return_dict.get('idNo') and len(return_dict['idNo']) == 18 and len(return_dict.get('gender', '')) != 1:
        tag = int(return_dict['idNo'][16]) % 2
        return_dict['gender'] = '女' if tag == 0 else '男'
    if not return_dict['idNo']:
        no = re.findall(r'\d{17}[\d|x|X]{1}', return_dict['address'], re.M|re.I)
        return_dict['idNo'] = no[0] if len(no) > 0 else ''
        return_dict['address'] = return_dict['address'].replace(return_dict['idNo'], '')
        # return_dict['idNo'] = re.findall(r'[1-9]\d{5}(?:18|19|(?:[23]\d))\d{2}(?:(?:0[1-9])|(?:10|11|12))(?:(?:[0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]', return_dict['address'], re.M|re.I)
    return_dict['source_str_arr'] = source_str_arr
    return json(res)


@app.post("/idback/predict")
async def hello_world(request):
    res = {
        'msg': 'ok',
        'code': 0,
        'data': {
            "indate": "",
            "sign": "",
            "source_str_arr": []
        }
    }
    if len(request.files.keys()) != 1:
        res['msg'] = '必须传入一个图片'
        res['code'] = 1
        return json(res)
    f = request.files.get(list(request.files.keys())[0])
    input_img = cv2.imdecode(np.frombuffer(f.body, np.uint8), cv2.IMREAD_COLOR)
    return_dict = res['data']
    res_ls = []
    try:
        result = app.config['back_ocr'].ocr(input_img)
        for line in result:
            res_ls.append(line[1][0])
    except Exception as e:
        logger.exception(e)
    source_str_arr = []
    for item in res_ls:
        try:
            item = item.replace(' ', '').replace('：', '')
            if '公安' in item:
                return_dict['sign'] = item.replace('签发机关', '').replace('发机关', '').replace('机关', '')
            elif '-' in item and not return_dict['indate']:
                return_dict['indate'] = item.replace('有效期限', '').replace('.', '')
            elif '—' in item and not return_dict['indate']:
                return_dict['indate'] = item.replace('有效期限', '').replace('.', '').replace('—', '-')
            elif item in ['中华人民共和国', '居民身份证', '签发机关', '有效期限']:
                continue
        except Exception as e:
            logger.error(f'error {e}')
        source_str_arr.append(item)
    return_dict['source_str_arr'] = source_str_arr
    if return_dict['indate'] and '-' in return_dict['indate']:
        start_date = return_dict['indate'].split('-')[0].replace('.', '')
        end_date = return_dict['indate'].split('-')[1].replace('.', '')
        if '长' in end_date:
            end_date = '长期'
        elif len(end_date) == 8:
            end_date = '%s.%s.%s' % (end_date[:4], end_date[4:6], end_date[6:])
        if len(start_date) == 8:
            start_date = '%s.%s.%s' % (start_date[:4], start_date[4:6], start_date[6:])
        return_dict['indate'] = '%s-%s' % (start_date, end_date)
    return json(res)


if __name__ == "__main__":
    app.run(host='0.0.0.0', port='18083', debug=False)